<template>
  <div ref="container" style="width: 100%; height: 500px; touch-action: none;"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, reactive } from 'vue'
import { Graph } from '@antv/x6'
import Hierarchy from '@antv/hierarchy'
import Hammer from 'hammerjs'
import { nodeData } from './orgChartData'
import { Export } from '@antv/x6-plugin-export'

/* 手势临时变量 */
let currentScale = 1
let pinchCenter = { x: 0, y: 0 }
let hammer: HammerManager | null = null
const container = ref<HTMLDivElement>()
let graph: any = null

// 定义组件的props
const props = defineProps({
  data: {
    type: Object,
    default: () => nodeData
  },
  width: {
    type: Number,
    default: 375
  },
  height: {
    type: Number,
    default: 500
  }
})

// 添加节点展开状态管理
const nodeStates = reactive<Record<string, boolean>>({})

onMounted(() => {
  // 创建图实例
  graph = new Graph({
    container: container.value!,
    width: props.width,
    height: props.height,
    grid: {
      size: 10,
      visible: false
    },
    panning: {
      enabled: true,
      eventTypes: ['leftMouseDown', 'rightMouseDown',]
    },
    mousewheel: {
      enabled: true,
      zoomAtMousePosition: true,
      factor: 1.1,
      minScale: 0.2,
      maxScale: 2.0
    },
    highlighting: {
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          attrs: {
            fill: '#5F95FF',
            stroke: '#5F95FF'
          }
        }
      }
    },
    connecting: {
      anchor: 'orth',
    },
    // 禁用节点拖拽
    interacting: {
      nodeMovable: false,
      edgeMovable: false,
      arrowheadMovable: false,
      edgeLabelMovable: false,
      magnetConnectable: false,
    },
  })

  // 注册导出插件
  graph.use(new Export())

  // 注册组织架构图节点（修改markup以支持折叠按钮）
  Graph.registerNode(
    'org-node',
    {
      width: 180,
      height: 60,
      markup: [
        {
          tagName: 'rect',
          selector: 'body',
        },
        {
          tagName: 'image',
          selector: 'avatar',
        },
        {
          tagName: 'text',
          selector: 'rank',
        },
        {
          tagName: 'text',
          selector: 'name',
        },
        // 添加折叠按钮组
        {
          tagName: 'g',
          selector: 'buttonGroup',
          children: [
            {
              tagName: 'rect',
              selector: 'button',
              attrs: {
                'pointer-events': 'visiblePainted',
              },
            },
            {
              tagName: 'path',
              selector: 'buttonSign',
              attrs: {
                fill: 'none',
                'pointer-events': 'none',
              },
            },
          ],
        },
      ],
      attrs: {
        body: {
          refWidth: '100%',
          refHeight: '100%',
          fill: '#5F95FF',
          stroke: '#5F95FF',
          strokeWidth: 1,
          rx: 10,
          ry: 10,
          pointerEvents: 'visiblePainted',
        },
        avatar: {
          width: 48,
          height: 48,
          refX: 8,
          refY: 6,
        },
        rank: {
          refX: 0.85,
          refY: 0.2,
          fill: '#fff',
          fontFamily: 'Courier New',
          fontSize: 14,
          textAnchor: 'end',
          textDecoration: 'underline',
        },
        name: {
          refX: 0.85,
          refY: 0.6,
          fill: '#fff',
          fontFamily: 'Courier New',
          fontSize: 14,
          fontWeight: '800',
          textAnchor: 'end',
        },
        // 折叠按钮样式
        buttonGroup: {
          refX: 175,  // 改为节点宽度，确保在最右边
          refY: 30,   // 垂直居中(60高度的一半)
          transform: 'translate(-16, -8)' // 调整X轴补偿为按钮完整宽度
        },
        button: {
          fill: '#5F95FF',
          stroke: '#ffffff',
          strokeWidth: 1,
          x: 0,        // 改为0，使矩形右边缘与g元素对齐
          y: 0,       // 保持垂直居中
          height: 16,
          width: 16,
          rx: 10,
          ry: 10,
          cursor: 'pointer',
          event: 'node:collapse',
        },
        buttonSign: {
          refX: 0,
          refY: 0,
          stroke: '#ffffff',
          strokeWidth: 1.6,
          // 调整路径数据使其居中
          d: 'M 8 2 8 14 M 2 8 14 8' // 这个路径数据本身已经居中于16x16的区域内
        }
      },
    },
    true,
  )

  Graph.registerEdge(
    'org-edge',
    {
      zIndex: -1,
      attrs: {
        line: {
          fill: 'none',
          strokeLinejoin: 'round',
          strokeWidth: 2,
          stroke: '#A2B1C3',
          sourceMarker: null,
          targetMarker: null,
        },
      },
    },
    true,
  )

  // 渲染组织架构图
  renderOrganizationChart(props.data)

  // 添加节点折叠事件监听
  graph.on('node:collapse', ({ node }: { node: any }) => {
    const nodeId = node.id
    toggleNodeCollapse(nodeId)
  })

  /* 2. 绑定 Hammer */
  const el = container.value!
  hammer = new Hammer(el)
  hammer.get('pinch').set({ enable: true })
  hammer.on('pinchstart', onPinchStart)
  hammer.on('pinchmove', onPinchMove)
  hammer.on('pinchend', onPinchEnd)

  // 添加触摸拖拽画布支持
  let lastPanCenter: { x: any; y: any } | null = null

  hammer.get('pan').set({ direction: Hammer.DIRECTION_ALL })

  hammer.on('panstart', (e) => {
    if (graph) {
      lastPanCenter = { x: e.center.x, y: e.center.y }
    }
  })

  hammer.on('panmove', (e) => {
    if (graph && lastPanCenter) {
      const dx = e.center.x - lastPanCenter.x
      const dy = e.center.y - lastPanCenter.y

      const currentTranslate = graph.translate()
      graph.translate(currentTranslate.tx + dx, currentTranslate.ty + dy)

      lastPanCenter = { x: e.center.x, y: e.center.y }
    }
  })

  hammer.on('panend', () => {
    lastPanCenter = null
  })
})

// 监听数据变化
watch(() => props.data, (newData) => {
  if (graph) {
    graph.clearCells()
    renderOrganizationChart(newData)
  }
}, { deep: true })

// 监听尺寸变化
watch(() => [props.width, props.height], ([newWidth, newHeight]) => {
  if (graph) {
    graph.resize(newWidth, newHeight)
  }
})

// 添加在 renderOrganizationChart 函数之前
const convertNodeData = (data: any) => {
  if (!data) return null;

  const convert = (node: any) => {
    return {
      id: node.id,
      label: node.name,
      manager: node.manager,
      gender: node.gender,
      staffCount: node.staffCount,
      children: node.childrenNodes ? node.childrenNodes.map(convert) : []
    };
  };

  if (Array.isArray(data)) {
    return data.map(convert);
  } else {
    return convert(data);
  }
};

// 切换节点折叠状态
const toggleNodeCollapse = (nodeId: string) => {
  // 切换节点状态
  nodeStates[nodeId] = !nodeStates[nodeId]
  // 重新渲染图表
  renderOrganizationChart(props.data)
}

// 修改 renderOrganizationChart 函数
const renderOrganizationChart = (data: any) => {
  if (!data || !graph) return

  // 转换数据格式以适配组件
  const convertedData = convertNodeData(data);
  const hierarchyData = Array.isArray(convertedData) ?
    { id: 'root', label: '组织架构', name: "公司名称", children: convertedData } :
    convertedData;

  // 创建节点ID到原始数据的映射
  const nodeDataMap: Record<string, any> = {};
  const buildNodeMap = (node: any) => {
    if (node) {
      nodeDataMap[node.id] = node;
      if (node.children) {
        node.children.forEach(buildNodeMap);
      }
    }
  };
  if (hierarchyData && Array.isArray(hierarchyData.children)) {
    hierarchyData.children.forEach(buildNodeMap);
  }

  // 使用层级布局算法计算节点位置
  const result = Hierarchy.mindmap(hierarchyData, {
    direction: 'TB',
    getHeight() {
      return 60
    },
    getWidth() {
      return 180
    },
    getHGap() {
      return 40
    },
    getVGap() {
      return 40
    },
    getSide: () => {
      return 'bottom'
    },
  })

  // 构建模型数据，使用原来的org-node样式
  const model: { nodes: any[], edges: any[] } = { nodes: [], edges: [] }
  // 节点男女头像图标
  const genderAvatarMap: Record<string, string> = {
    '男': 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ',
    '女': 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ'
  };

  // 修改traverse函数以支持折叠
  const traverse = (data: any, parentCollapsed: boolean = false) => {
    // 只有当节点未被父节点折叠时才处理当前节点
    if (data && !parentCollapsed) {
      // 从映射中获取原始数据
      const originalData = nodeDataMap[data.id] || data;

      // 检查节点是否有子节点
      const hasChildren = originalData.children && originalData.children.length > 0;

      // 设置折叠按钮符号
      let buttonSignPath = ''
      if (hasChildren) {
        // 根据节点状态设置符号 (+ 或 -)
        if (nodeStates[data.id]) {
          buttonSignPath = 'M 8 2 8 14 M 2 8 14 8' // 十字 (+) - 折叠状态显示加号
        } else {
          buttonSignPath = 'M 2 8 14 8' // 横线 (-) - 展开状态显示减号
        }
      }

      model.nodes.push({
        id: `${data.id}`,
        x: data.x + 300,
        y: data.y + 50,
        shape: 'org-node',
        attrs: {
          avatar: {
            opacity: 0.7,
            'xlink:href': originalData.gender ? genderAvatarMap[originalData.gender] : genderAvatarMap['男'],
          },
          rank: {
            text: originalData.label || originalData.name || '组织架构图-部门',
            wordSpacing: '-5px',
            letterSpacing: 0,
          },
          name: {
            text: originalData.manager || '主要管理人员',
            fontSize: 13,
            fontFamily: 'Arial',
            letterSpacing: 0,
          },
          // 设置折叠按钮显示状态
          buttonGroup: {
            display: hasChildren ? 'block' : 'none',
          },
          buttonSign: {
            d: buttonSignPath,
          },
        },
      })

      // 检查当前节点是否折叠
      const isCollapsed = nodeStates[data.id] === true;

      // 只有在节点未折叠时才处理子节点
      if (data.children && !isCollapsed) {
        data.children.forEach((item: any) => {
          // 添加连接线
          model.edges.push({
            source: `${data.id}`,
            target: `${item.id}`,
            shape: 'org-edge',
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 2,
                sourceMarker: null,
                targetMarker: null,
              },
            },
          })
          // 递归处理子节点，传递当前节点的折叠状态
          traverse(item, isCollapsed)
        })
      }
    }
  }
  traverse(result)
  graph.fromJSON(model)
  graph.zoomToFit({ padding: 20, maxScale: 1 })
}

/* ===== 手势回调 ===== */
function onPinchStart(e: HammerInput) {
  currentScale = graph.zoom()
  const rect = container.value!.getBoundingClientRect()
  pinchCenter = {
    x: e.center.x - rect.left,
    y: e.center.y - rect.top,
  }
}

function onPinchMove(e: HammerInput) {
  let nextScale = currentScale * e.scale
  nextScale = Math.min(Math.max(nextScale, 0.2), 2.0)
  graph.zoom(nextScale, {
    absolute: true,
    center: pinchCenter,
  })
}

function onPinchEnd() {
  // 可在此持久化缩放值或做动画回弹
}

onBeforeUnmount(() => {
  hammer?.destroy()
  graph?.dispose()
})

const exportToImage = async () => {
  if (graph) {
    try {
      graph.exportSVG("组织架构图", {})
    } catch (error) {
      console.error('导出图片失败:', error)
    }
  } else {
    console.warn('图表未初始化，无法导出图片')
  }
}

// 暴露给父组件调用
defineExpose({
  exportToImage
})
</script>